package com.rpc.provider.service;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * 发布服务
 *
 *
 */
public class RpcProxyServer  {

    // 处理请求的线程
    private ExecutorService executorService = Executors.newCachedThreadPool();

    // 发布的服务集合
    private ConcurrentHashMap concurrentHashMap = new ConcurrentHashMap();

    // 单例模式，启动服务，发布服务
    private static RpcProxyServer rpcProxyServer = new RpcProxyServer();

    private RpcProxyServer() {}

    public static RpcProxyServer getInstance(){
        return rpcProxyServer;
    }

    public void startServer(int port){

        ServerSocket serverSocket = null;

        try {
            serverSocket = new ServerSocket(port);
            System.out.println("服务端开始提供服务...");
            while (true) {

                Socket socket = serverSocket.accept();
                executorService.execute(new ProcessorHandler(socket));
            }

        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            if (serverSocket != null){
                try {
                    serverSocket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

    }

    /**
     * rpc 对外暴露的是 api 接口，发布服务的时候也根据 接口发布，每个节点只会有一个实现，可自己定义策略选择发布的服务
     * 发布的服务 会存在于 concurrentHash 中，key 值为接口信息，value 为实现类
     * @param serviceImpl
     */
    public void publishor(Object serviceImpl){

        Class<?>[] interfaces = serviceImpl.getClass().getInterfaces();
        for(int i=0;i<interfaces.length;i++){

            if(!canPublish(interfaces[i].getName())) continue;
            concurrentHashMap.put(interfaces[i].getName(), serviceImpl);
        }
    }

    /**
     * 获取发布的服务信息
     * @param interfaceName
     * @return
     */
    public Object getServiceImpl(String interfaceName) throws Exception {

        if(concurrentHashMap.containsKey(interfaceName)){
            return concurrentHashMap.get(interfaceName);
        }
        throw new Exception("dosn't has this service!");
    }

    /**
     * 接口是否可以发布
     * @param name
     * @return
     */
    private boolean canPublish(String name) {

        return true;
    }

}
